#include <dbus/dbus.h>
#include <string>
#include <sstream>
#include <iostream>
#include <map>
#include <tcl.h>
#include <tk.h>
#include "dbus/dbus.h"
#include "Controller.h"
#include "IdGenerator.h"
#include "XanguliException.h"

namespace Xanguli {

int xanguli_command(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  std::string widget_path;
  int widget_path_len;
  std::string signal;
  int signal_len;

  if (3 != objc) {
    ::Tcl_WrongNumArgs(interp, 1, objv, "widget command_name");
    return TCL_ERROR;
  }

  widget_path = Tcl_GetStringFromObj(objv[1], &widget_path_len);

  signal = Tcl_GetStringFromObj(objv[2], &signal_len);

  /*
   * TODO:
   * send signal 'signal' on the object owning 'widget_path'
   */

  return TCL_OK;
}

Controller::Controller() {
  interp = Tcl_CreateInterp();

  if (Tcl_Init(interp) != TCL_OK) {
	  throw new XanguliException("Could not initiate interpreter\n");
  }
  if (Tcl_Eval(interp, "package require Tk") != TCL_OK) {
	  throw new XanguliException("Could not initiate tk");
  }
  if (Tcl_Eval(interp, "package require Ttk") != TCL_OK) {
	  throw new XanguliException("Could not initiate ttk");
  }
  // Make a callback hook for tcl commands
  Tcl_CreateObjCommand (interp, "xanguli_command", xanguli_command, NULL, NULL);

  // TODO Make callback for bindings...
}


void Controller::CreateWidget(std::string widget,
		                      std::string parent,
		                      std::map<std::string, Variant> options,
						      std::string &dbus_id) {
	std::cout << "CreateWidget\n";
	std::cout << "widget = " << widget << "\n";
	std::cout << "parent = " << parent << "\n";
	std::stringstream ss;

	dbus_id = IdGenerator::newPath(widget, parent);
	char* tcl_id = (char*) dbus_id.c_str();
	int i = 0;
	for (char* c = tcl_id; *c; c++) {
		if (*c == '/') *c = '.';
	}
	std::cout << "Controller, building command\n";
	ss << widget << " " << tcl_id << " ";

	for(std::map<std::string, Variant>::const_iterator it = options.begin(); it != options.end(); it++) {
		std::string key = (*it).first;
		Variant val = (*it).second;
		std::cout << "(" << key << ", " << val.asString() << ")\n";
		ss << "-" << key << " " << val.asString() << " ";
	}

	std::cout << "Tcl commando: " << ss.str() << "\n";
	if (Tcl_Eval(interp, ss.str().c_str()) != TCL_OK) {
		throw new XanguliException("TclError");
	}
}

void Controller::tkMainloop() {
  Tk_MainLoop();
}

}
